package com.tsfyun.scm.service.impl.report;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tsfyun.common.base.config.OrikaBeanMapper;
import com.tsfyun.common.base.dto.Result;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.security.SecurityUtil;
import com.tsfyun.common.base.util.DateUtils;
import com.tsfyun.common.base.util.PageUtil;
import com.tsfyun.common.base.util.StringUtils;
import com.tsfyun.common.base.validator.ValidatorUtils;
import com.tsfyun.scm.client.CustomsCodeClient;
import com.tsfyun.scm.dto.file.ExcelKeyValue;
import com.tsfyun.scm.dto.file.ExportExcelParamsDTO;
import com.tsfyun.scm.dto.order.ExpOrderReceiveQTO;
import com.tsfyun.scm.dto.report.ExpOneVoteTheEndQTO;
import com.tsfyun.scm.dto.view.ViewExpDifferenceMemberQTO;
import com.tsfyun.scm.mapper.order.ExpOrderMapper;
import com.tsfyun.scm.mapper.view.ViewExpDifferenceMemberMapper;
import com.tsfyun.scm.mapper.view.ViewExpOrderCostMemberMapper;
import com.tsfyun.scm.service.file.IExportFileService;
import com.tsfyun.scm.service.finance.IExpPaymentAccountService;
import com.tsfyun.scm.service.finance.IOverseasReceivingAccountService;
import com.tsfyun.scm.service.order.IExpOrderMemberService;
import com.tsfyun.scm.service.report.IExpReportService;
import com.tsfyun.scm.system.vo.CustomsCodeVO;
import com.tsfyun.scm.vo.report.ExpOneVoteTheEndVO;
import com.tsfyun.scm.vo.report.MonthCostVO;
import com.tsfyun.scm.vo.view.ViewExpDifferenceMemberVO;
import com.tsfyun.scm.vo.view.ViewExpDifferenceSummaryVO;
import com.tsfyun.scm.vo.view.ViewExpOrderCostMemberTotalVO;
import com.tsfyun.scm.vo.view.ViewExpOrderCostMemberVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 * @Description:
 * @CreateDate: Created in 2021/10/18 12:38
 */
@Service
public class ExpReportServiceImpl implements IExpReportService {

    @Autowired
    private ViewExpDifferenceMemberMapper viewExpDifferenceMemberMapper;
    @Autowired
    private ExpOrderMapper expOrderMapper;
    @Autowired
    private IExpOrderMemberService expOrderMemberService;
    @Autowired
    private CustomsCodeClient customsCodeClient;
    @Autowired
    private IExportFileService exportService;
    @Autowired
    private IOverseasReceivingAccountService overseasReceivingAccountService;
    @Autowired
    private IExpPaymentAccountService expPaymentAccountService;
    @Autowired
    private ViewExpOrderCostMemberMapper viewExpOrderCostMemberMapper;

    @Autowired
    private OrikaBeanMapper beanMapper;

    @Override
    public PageInfo<ViewExpDifferenceMemberVO> expDifferenceMemberPage(ViewExpDifferenceMemberQTO qto) {
        PageHelper.startPage(qto.getPage(),qto.getLimit());
        List<ViewExpDifferenceMemberVO> list = viewExpDifferenceMemberMapper.expDifferenceMemberList(qto);
        return new PageInfo<>(list);
    }

    @Override
    public BigDecimal obtainCustomerExpDifferenceVal(Long customerId) {
        return viewExpDifferenceMemberMapper.getDifferenceVal(customerId);
    }

    @Override
    public Long exportExpDifferenceMember(ViewExpDifferenceMemberQTO qto) throws Exception {
        List<ViewExpDifferenceMemberVO> list = viewExpDifferenceMemberMapper.expDifferenceMemberList(qto);
        ExportExcelParamsDTO params = new ExportExcelParamsDTO();
        params.setFileName(String.format("出口票差明细%s", DateUtils.fromatShortNoSign(new Date())));
        params.setSheetName("出口票差明细");
        params.setOperator(SecurityUtil.getCurrentPersonIdAndName());
        params.setDatas(list);
        List<ExcelKeyValue> files = new ArrayList<ExcelKeyValue>(){{
            add(new ExcelKeyValue("docNo","订单编号"));
            add(new ExcelKeyValue("orderDate","订单日期"));
            add(new ExcelKeyValue("customerName","客户名称"));
            add(new ExcelKeyValue("purchaseContractNo","采购合同号"));
            add(new ExcelKeyValue("purchaseCny","采购合同总价"));
            add(new ExcelKeyValue("settleAccountCny","结汇人民币金额"));
            add(new ExcelKeyValue("actualPurchaseCny","实际采购金额"));
            add(new ExcelKeyValue("differenceVal","票差金额"));
            add(new ExcelKeyValue("adjustmentVal","票差调整金额"));
        }};
        params.setFiles(files);
        return exportService.exportExcel(params);
    }

    @Override
    public PageInfo<ViewExpDifferenceSummaryVO> expDifferenceSummaryPage(ViewExpDifferenceMemberQTO qto) {
        PageHelper.startPage(qto.getPage(),qto.getLimit());
        List<ViewExpDifferenceSummaryVO> list = viewExpDifferenceMemberMapper.expDifferenceSummaryList(qto);
        return new PageInfo<>(list);
    }

    @Override
    public Long exportExpDifferenceSummary(ViewExpDifferenceMemberQTO qto) throws Exception {
        List<ViewExpDifferenceSummaryVO> list = viewExpDifferenceMemberMapper.expDifferenceSummaryList(qto);
        ExportExcelParamsDTO params = new ExportExcelParamsDTO();
        params.setFileName(String.format("出口票差汇总%s", DateUtils.fromatShortNoSign(new Date())));
        params.setSheetName("出口票差汇总");
        params.setOperator(SecurityUtil.getCurrentPersonIdAndName());
        params.setDatas(list);
        List<ExcelKeyValue> files = new ArrayList<ExcelKeyValue>(){{
            add(new ExcelKeyValue("customerName","客户名称"));
            add(new ExcelKeyValue("differenceVal","票差金额"));
        }};
        params.setFiles(files);
        return exportService.exportExcel(params);
    }

    @Override
    public PageInfo<ViewExpOrderCostMemberVO> orderReceivableList(ExpOrderReceiveQTO qto) {
        PageHelper.startPage(qto.getPage(),qto.getLimit());
        Map<String,Object> params = beanMapper.map(qto,Map.class);
        List<ViewExpOrderCostMemberVO> list = viewExpOrderCostMemberMapper.orderReceivableList(params);
        return new PageInfo<>(list);
    }

    @Override
    public ViewExpOrderCostMemberTotalVO orderReceivableTotal(ExpOrderReceiveQTO qto) {
        Map<String,Object> params = beanMapper.map(qto,Map.class);
        return viewExpOrderCostMemberMapper.orderReceivableTotal(params);
    }

    @Override
    public Long orderReceivableExport(ExpOrderReceiveQTO qto) throws Exception {
        Map<String,Object> params = beanMapper.map(qto,Map.class);
        List<ViewExpOrderCostMemberVO> list = viewExpOrderCostMemberMapper.orderReceivableList(params);
        ExportExcelParamsDTO excelParams = new ExportExcelParamsDTO();
        excelParams.setFileName(String.format("出口订单应收%s", DateUtils.fromatShortNoSign(new Date())));
        excelParams.setSheetName("出口订单应收");
        excelParams.setOperator(SecurityUtil.getCurrentPersonIdAndName());
        excelParams.setDatas(list);
        List<ExcelKeyValue> files = new ArrayList<ExcelKeyValue>(){{
            add(new ExcelKeyValue("orderNo","订单编号"));
            add(new ExcelKeyValue("orderDate","订单日期"));
            add(new ExcelKeyValue("customerName","客户名称"));
            add(new ExcelKeyValue("salePersonName","销售人员"));
            add(new ExcelKeyValue("totalPrice","出口金额"));
            add(new ExcelKeyValue("currencyName","币制"));
            add(new ExcelKeyValue("receAmount","应收金额"));
            add(new ExcelKeyValue("acceAmount","已收金额"));
        }};
        excelParams.setFiles(files);
        return exportService.exportExcel(excelParams);
    }



    @Override
    public Map<String, BigDecimal> monthAgencyFee(String year) {
        List<MonthCostVO> list = viewExpOrderCostMemberMapper.findMonthCost(year);
        if(CollectionUtil.isNotEmpty(list)){
            return list.stream().collect(Collectors.toMap(MonthCostVO::getMonth,(e)->e.getCost()));
        }
        return new LinkedHashMap<>();
    }

    @Override
    public Result<List<ExpOneVoteTheEndVO>> oneVoteTheEnd(ExpOneVoteTheEndQTO qto) {
        List<ExpOneVoteTheEndVO> list =  PageUtil.pageQ(qto,()->expOrderMapper.oneVoteTheEnd(beanMapper.map(qto,Map.class)));
        List<ExpOneVoteTheEndVO> dataList = new ArrayList<>();
        // 海关编码
        Map<String, CustomsCodeVO> hsCodeMap = new LinkedHashMap<>();
        Integer total = 0;
        if(CollectionUtil.isNotEmpty(list)){
            total = (int)new PageInfo<>(list).getTotal();
            for(int i=0;i<list.size();i++){
                List<ExpOneVoteTheEndVO> orderItemList = new ArrayList<>();
                ExpOneVoteTheEndVO item = list.get(i);
                // 查询订单明细
                List<ExpOneVoteTheEndVO> orderMembers = expOrderMemberService.oneVoteTheEndByOrderId(item.getOrderId());
                orderMembers.get(0).setIdx(i+1);
                for(ExpOneVoteTheEndVO orderMember : orderMembers){
                    if(StringUtils.isNotEmpty(orderMember.getHsCode())){
                        CustomsCodeVO codeVO = hsCodeMap.computeIfAbsent(orderMember.getHsCode(),(hsCode)->{
                            Result<CustomsCodeVO> codeVOResult = customsCodeClient.detail(hsCode);
                            if(codeVOResult.isSuccess()) {
                                return codeVOResult.getData();
                            }
                            return null;
                        });
                        // 退税率
                        orderMember.setTrr(Optional.ofNullable(codeVO).map(CustomsCodeVO::getTrr).orElse(""));
                    }
                    orderItemList.add(fullOrderData(orderMember,item));
                }
                // 订单未结汇金额
                orderItemList.get(0).setNoSettlementValue(item.getNoSettlementValue());

                orderItemList.get(0).setPurchaseValue(item.getPurchaseValue());
                orderItemList.get(0).setActualPurchaseValue(item.getActualPurchaseValue());
                orderItemList.get(0).setDifferenceVal(item.getDifferenceVal());
                orderItemList.get(0).setAdjustmentVal(item.getAdjustmentVal());
                orderItemList.get(0).setInvoicingDate(item.getInvoicingDate());
                orderItemList.get(0).setInvoiceDate(item.getInvoiceDate());
                orderItemList.get(0).setInvoiceNo(item.getInvoiceNo());
                orderItemList.get(0).setInvoiceVal(item.getInvoiceVal());

                orderItemList.get(0).setTaxDeclareTime(item.getTaxDeclareTime());
                orderItemList.get(0).setTaxDeclareAmount(item.getTaxDeclareAmount());
                orderItemList.get(0).setTaxRefundTime(item.getTaxRefundTime());
                orderItemList.get(0).setTaxRefundAmount(item.getTaxRefundAmount());
                orderItemList.get(0).setIsCorrespondence(item.getIsCorrespondence());
                orderItemList.get(0).setReplyStatus(item.getReplyStatus());
                orderItemList.get(0).setReplyDate(item.getReplyDate());

                orderItemList.get(0).setDrawbackNo(item.getDrawbackNo());
                orderItemList.get(0).setActualDrawbackValue(item.getActualDrawbackValue());
                orderItemList.get(0).setAlreadyDrawbackValue(item.getAlreadyDrawbackValue());
                if(Objects.nonNull(item.getActualDrawbackValue()) && Objects.nonNull(item.getAlreadyDrawbackValue())){
                    orderItemList.get(0).setUnpaidDrawbackValue(
                            item.getActualDrawbackValue().subtract(item.getAlreadyDrawbackValue()).setScale(2,BigDecimal.ROUND_HALF_UP)
                    );
                }

                if(Objects.nonNull(item.getInvoiceVal()) && item.getInvoiceVal().compareTo(BigDecimal.ZERO) == 1){
                    BigDecimal taxInvVal = item.getInvoiceVal().multiply(BigDecimal.valueOf(0.13)).setScale(2,BigDecimal.ROUND_HALF_UP);
                    orderItemList.get(0).setTaxInvVal(taxInvVal);
                    orderItemList.get(0).setVatInvVal(item.getInvoiceVal().subtract(taxInvVal).setScale(2,BigDecimal.ROUND_HALF_UP));
                }

                // 查询境外收款单
                List<ExpOneVoteTheEndVO> receivingExpOneVoteTheEndList = overseasReceivingAccountService.oneVoteTheEndByOrderId(item.getOrderId());
                if(CollectionUtil.isNotEmpty(receivingExpOneVoteTheEndList)){
                    if(receivingExpOneVoteTheEndList.size()>orderItemList.size()){
                        int csize = receivingExpOneVoteTheEndList.size()-orderItemList.size();
                        for(int b=0;b<csize;b++){
                            ExpOneVoteTheEndVO blankLineVO = new ExpOneVoteTheEndVO();
                            blankLineVO.setOrderId(item.getOrderId());
                            blankLineVO.setOrderNo(item.getOrderNo());
                            orderItemList.add(blankLineVO);
                        }
                    }
                    for(int r=0;r<receivingExpOneVoteTheEndList.size();r++){
                        ExpOneVoteTheEndVO receivingVO = receivingExpOneVoteTheEndList.get(r);
                        orderItemList.get(r).setReceivingNo(receivingVO.getReceivingNo());
                        orderItemList.get(r).setReceivingDate(receivingVO.getReceivingDate());
                        orderItemList.get(r).setAmountReceived(receivingVO.getAmountReceived());
                        orderItemList.get(r).setReceivingFee(receivingVO.getReceivingFee());
                        orderItemList.get(r).setOrderClaimValue(receivingVO.getOrderClaimValue());
                        orderItemList.get(r).setReceivingCurrency(receivingVO.getReceivingCurrency());
                        orderItemList.get(r).setSettlementNo(receivingVO.getSettlementNo());
                    }
                }
                // 查询付款单
                List<ExpOneVoteTheEndVO> paymentExpOneVoteTheEndList = expPaymentAccountService.oneVoteTheEndByOrderId(item.getOrderId());
                if(CollectionUtil.isNotEmpty(paymentExpOneVoteTheEndList)){
                    for(int r=0;r<paymentExpOneVoteTheEndList.size();r++) {
                        ExpOneVoteTheEndVO receivingVO = paymentExpOneVoteTheEndList.get(r);
                        orderItemList.get(r).setPaymentNo(receivingVO.getPaymentNo());
                        orderItemList.get(r).setPaymentDate(receivingVO.getPaymentDate());
                        orderItemList.get(r).setSettlementRate(receivingVO.getSettlementRate());
                        orderItemList.get(r).setPaymentValue(receivingVO.getPaymentValue());
                    }
                }

                dataList.addAll(orderItemList);
            }
        }
        return Result.success(total,dataList);
    }

    @Override
    public Long exportOneVoteTheEnd(ExpOneVoteTheEndQTO qto) throws Exception {
        qto.setLimit(10000);
        Result<List<ExpOneVoteTheEndVO>> dataResult = this.oneVoteTheEnd(qto);
        ValidatorUtils.isTrue(dataResult.isSuccess(),()->new ServiceException("导出异常，请稍后再试"));
        ExportExcelParamsDTO excelParams = new ExportExcelParamsDTO();
        excelParams.setFileName(StrUtil.format("出口一票到底{}", DateUtils.fromatShortNoSign(new Date())));
        excelParams.setSheetName("出口一票到底");
        excelParams.setShowIndex(false);
        excelParams.setOperator(SecurityUtil.getCurrentPersonIdAndName());
        excelParams.setDatas(dataResult.getData());
        List<ExcelKeyValue> files = new ArrayList<ExcelKeyValue>(){{
            add(new ExcelKeyValue("idx","序号"));
            add(new ExcelKeyValue("orderStatusDesc","状态"));
            add(new ExcelKeyValue("orderNo","订单编号"));
            add(new ExcelKeyValue("clientOrderNo","客户单号"));
            add(new ExcelKeyValue("orderDate","订单日期"));
            add(new ExcelKeyValue("customerName","客户名称"));
            add(new ExcelKeyValue("name","品名"));
            add(new ExcelKeyValue("brand","品牌"));
            add(new ExcelKeyValue("model","型号"));
            add(new ExcelKeyValue("hsCode","海关编码"));
            add(new ExcelKeyValue("trr","退税率"));
            add(new ExcelKeyValue("unitPrice","单价"));
            add(new ExcelKeyValue("quantity","数量"));
            add(new ExcelKeyValue("totalPrice","出口金额"));
            add(new ExcelKeyValue("currencyName","订单币制"));
            add(new ExcelKeyValue("quoteDescribe","代理协议"));
            add(new ExcelKeyValue("agencyFee","代理费率"));
            add(new ExcelKeyValue("minAgencyFee","最低收费"));
            add(new ExcelKeyValue("agencyFeeCost","应收代理费"));
            add(new ExcelKeyValue("agentName","申报单位"));
            add(new ExcelKeyValue("decDate","通关日期"));
            add(new ExcelKeyValue("declarationNo","报关单号"));
            add(new ExcelKeyValue("ciqEntyPortName","通关口岸"));
            add(new ExcelKeyValue("cartonNum","箱数"));
            add(new ExcelKeyValue("plateNum","板数"));
            add(new ExcelKeyValue("cusVoyageNo","国际运单号"));
            add(new ExcelKeyValue("cusTrafModeName","运输方式"));
            add(new ExcelKeyValue("conveyanceType","订单车型"));
            add(new ExcelKeyValue("conveyanceNo","大陆车牌"));
            add(new ExcelKeyValue("conveyanceNo2","香港车牌"));
            add(new ExcelKeyValue("transportSupplierName","承运公司"));
            add(new ExcelKeyValue("shippingCompany","发货单位"));
            add(new ExcelKeyValue("shippingAddress","发货地址"));
            add(new ExcelKeyValue("shippingLinkPerson","发货联系人"));
            add(new ExcelKeyValue("shippingLinkTel","发货联系电话"));
            add(new ExcelKeyValue("deliveryCompany","收货单位"));
            add(new ExcelKeyValue("deliveryAddress","收货地址"));
            add(new ExcelKeyValue("deliveryLinkPerson","收货联系人"));
            add(new ExcelKeyValue("deliveryLinkTel","收货联系电话"));
            add(new ExcelKeyValue("receivingNo","境外收款单号"));
            add(new ExcelKeyValue("receivingDate","收款日期"));
            add(new ExcelKeyValue("amountReceived","到账金额"));
            add(new ExcelKeyValue("receivingCurrency","收款币制"));
            add(new ExcelKeyValue("receivingFee","手续费"));
            add(new ExcelKeyValue("orderClaimValue","本单认领金额"));

            add(new ExcelKeyValue("paymentNo","付款单号"));
            add(new ExcelKeyValue("paymentDate","付款时间"));
            add(new ExcelKeyValue("settlementRate","结汇汇率"));
            add(new ExcelKeyValue("paymentValue","已付结汇金额CNY"));

            add(new ExcelKeyValue("noSettlementValue","未结汇金额"));
            add(new ExcelKeyValue("currencyName","未结汇币制"));

            add(new ExcelKeyValue("settlementNo","结汇单号"));
            add(new ExcelKeyValue("purchaseValue","采购合同金额"));
            add(new ExcelKeyValue("actualPurchaseValue","应开发票金额"));
            add(new ExcelKeyValue("differenceVal","产生票差"));
            add(new ExcelKeyValue("adjustmentVal","调整票差"));
            add(new ExcelKeyValue("invoicingDate","开票日期"));
            add(new ExcelKeyValue("invoiceDate","收票日期"));
            add(new ExcelKeyValue("invoiceNo","发票号码"));
            add(new ExcelKeyValue("invoiceVal","收票金额"));
            add(new ExcelKeyValue("vatInvVal","增票金额"));
            add(new ExcelKeyValue("taxInvVal","增票税额"));
            add(new ExcelKeyValue("drawbackNo","退税付款单号"));
            add(new ExcelKeyValue("actualDrawbackValue","应付退税款"));
            add(new ExcelKeyValue("alreadyDrawbackValue","已付退税款"));
            add(new ExcelKeyValue("unpaidDrawbackValue","未付退税款"));
            add(new ExcelKeyValue("taxDeclareTime","退税申报日期"));
            add(new ExcelKeyValue("taxDeclareAmount","退税申报金额"));
            add(new ExcelKeyValue("taxRefundTime","税局退税日期"));
            add(new ExcelKeyValue("taxRefundAmount","税局退税金额"));
            add(new ExcelKeyValue("isCorrespondenceDesc","是否函调"));
            add(new ExcelKeyValue("replyStatus","是否回调"));
            add(new ExcelKeyValue("replyDate","回函日期"));
        }};
        excelParams.setFiles(files);
        return exportService.exportExcel(excelParams);
    }

    private ExpOneVoteTheEndVO fullOrderData(ExpOneVoteTheEndVO v1,ExpOneVoteTheEndVO v2){
        v1.setOrderStatus(v2.getOrderStatus());
        v1.setOrderNo(v2.getOrderNo());
        v1.setClientOrderNo(v2.getClientOrderNo());
        v1.setOrderDate(v2.getOrderDate());
        v1.setCustomerId(v2.getCustomerId());
        v1.setCustomerName(v2.getCustomerName());
        v1.setCurrencyId(v2.getCurrencyId());
        v1.setCurrencyName(v2.getCurrencyName());
        v1.setQuoteDescribe(v2.getQuoteDescribe());
        v1.setAgencyFee(v2.getAgencyFee());
        v1.setMinAgencyFee(v2.getMinAgencyFee());
        v1.setAgencyFeeCost(v2.getAgencyFeeCost());
        v1.setAgentName(v2.getAgentName());
        v1.setDecDate(v2.getDecDate());
        v1.setCiqEntyPortName(v2.getCiqEntyPortName());
        v1.setCusTrafModeName(v2.getCusTrafModeName());
        v1.setCusVoyageNo(v2.getCusVoyageNo());
        v1.setConveyanceType(v2.getConveyanceType());
        v1.setConveyanceNo(v2.getConveyanceNo());
        v1.setConveyanceNo2(v2.getConveyanceNo2());
        v1.setTransportSupplierName(v2.getTransportSupplierName());
        v1.setShippingCompany(v2.getShippingCompany());
        v1.setShippingAddress(v2.getShippingAddress());
        v1.setShippingLinkPerson(v2.getShippingLinkPerson());
        v1.setShippingLinkTel(v2.getShippingLinkTel());
        v1.setDeliveryCompany(v2.getDeliveryCompany());
        v1.setDeliveryAddress(v2.getDeliveryAddress());
        v1.setDeliveryLinkPerson(v2.getDeliveryLinkPerson());
        v1.setDeliveryLinkTel(v2.getDeliveryLinkTel());
        return v1;
    }
}
